/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package serv;

import IA.DistFS.*;
import aima.util.Pair;
import java.util.ArrayList;
import java.util.Set;

/**
 *
 * @author sendra
 */

    
//estic canviant la classe fitxer i arreglanto tot perk es guardi tot a requlist.java


public class Estado {
    public int[] TxServer;
    public ArrayList<ArrayList<Pair>> fitxers; 
    public ArrayList<Pair> trets;
	
    public int tamFix;
    public int tamTxServ;
    public static double temps;
	public static double solucio;
    //RequList fitxersaux;
   
    public Estado(int tamFitx, int tamTxServ){
	
		this.tamFix = tamFitx;
		this.tamTxServ = tamTxServ;
		fitxers = new ArrayList<ArrayList<Pair>>(tamTxServ);
		for(int i = 0; i < tamTxServ;++i){
			fitxers.add(new ArrayList<Pair>());
		}
		
		trets = new ArrayList<Pair>();
		
		this.TxServer = new int[tamTxServ];
		//inicialitzar totes les posicions a 0
		for (int i = 0; i <tamTxServ;++i){
			TxServer[i] = 0;
		}		
    }
	
	public Estado(Estado e){
		
		this.tamFix = e.tamFix;
		this.tamTxServ = e.tamTxServ;
		
		//CLONE fitxers
		this.fitxers = new ArrayList();
		for ( int i = 0 ; i < this.tamTxServ ; i++ ) {
			ArrayList serv = new ArrayList();
			for ( int j = 0 ; j < e.fitxers.get(i).size() ; j++ ) {
				Pair fitx = new Pair( e.fitxers.get(i).get(j).getFirst(), e.fitxers.get(i).get(j).getSecond() );
				serv.add(fitx);
			}
			this.fitxers.add(serv);
		}
		
		//CLONE trets
		this.trets = new ArrayList();
		for ( int i = 0 ; i < e.trets.size() ; i++ ) {
			Pair fitx = new Pair( e.trets.get(i).getFirst(), e.trets.get(i).getSecond() );
			this.trets.add(fitx);
		}
		
		//CLONE TxServer
		this.TxServer = (int[])e.TxServer.clone();
		
    }
	
    public void crearEstatInicial( Requests r, Servers s ){
        
        int idUser;
        int idFitxer;
        int idServer;
        
		for ( int i = 0 ; i <= this.tamFix ; i++ ) {

			int[] retFitx = r.getRequest(i);
			idUser = retFitx[0];
			idFitxer = retFitx[1];
			
			Set<Integer> retServ = s.fileLocations(idFitxer);
			Pair usrFitx = new Pair(idUser,idFitxer); 
			
			if ( Servi.SolucioInicialInteligent ) System.out.println("INICIAL INTELIGENT");
			else System.out.println("INICIAL RAPID");
			
			if ( Servi.SolucioInicialInteligent ) idServer = buscarServ(retServ);
			else idServer = retServ.iterator().next();
			
			fitxers.get(idServer).add(usrFitx);
			
			int tempsTrans = s.tranmissionTime(idServer, idUser);
			TxServer[idServer] = TxServer[idServer] + tempsTrans; 
			
		} 
		
		this.calculateTempsDescarga();
    }
	
	public void calculateTempsDescarga () {
		double temps_total = 0.0;
		for ( int i = 0 ; i < this.tamTxServ ; i++ ) {
			if ( this.TxServer[i] > temps_total )
				temps_total = this.TxServer[i];
		} 
		
		this.temps = temps_total;
	}
    public int calculateTotalFitxers(){
            int total_fitxers = 0;
            for ( int i = 0 ; i < Servi.maxServers ; i ++ ) {
		if ( fitxers.get(i).size() > 0 ) {
                    for ( int j = 0 ; j < fitxers.get(i).size() ; j++ ) {
			total_fitxers++;
                    }
		} 	
	    }
            return total_fitxers;
        }
	
	//@Override
	public String toString(double temps_ini) {
		String out = "";
		
		if ( Servi.SortidaR ) { //SORTIDA PER R
			int total_time = 0;
			int total_fitxers = 0;
			for ( int i = 0 ; i < Servi.maxServers ; i ++ ) {
				if ( fitxers.get(i).size() > 0 ) {
					if ( total_time < TxServer[i] ) total_time = TxServer[i];
					for ( int j = 0 ; j < fitxers.get(i).size() ; j++ ) total_fitxers++;
				} 	
			}
			//out = "\t" + (temps_ini - total_time) + "\t" + total_time + "\t	" + total_fitxers;
			out = "\t" + (temps_ini - total_time) + "\t" + solucio;
		}
		else { //SORTIDA PER NOSALTRES
			out = "\n\tTemps de servidors (id_server::temps_server):\n \t\t";

			String sFitxers = "";
			int total_time = 0;
			int total_fitxers = 0;
			for ( int i = 0 ; i < Servi.maxServers ; i ++ ) {
				if ( fitxers.get(i).size() > 0 ) {

					out += i + "::" + TxServer[i] + " | ";
					if ( total_time < TxServer[i] ) total_time = TxServer[i];


					int server_fitxers = 0;
					String sFitxersServer = "";
					for ( int j = 0 ; j < fitxers.get(i).size() ; j++ ) {
						sFitxersServer += "\t\t\t user:" + fitxers.get(i).get(j).getFirst();
						sFitxersServer += " - fitxer:" + fitxers.get(i).get(j).getSecond() + "\n";
						server_fitxers++;
						total_fitxers++;
					}
					sFitxers += "\t\tserver " + i + " (" + server_fitxers + "): \n" + sFitxersServer;
				} 	
			}
			out += "\n\n\t\tTemps total descargas: " + total_time + "\n";
			out += "\n\t# fitxers: " + total_fitxers + "\n";
			//out += "\n\tCua de descargas de servidors:\n" + sFitxers;


			String trets = "";
			int total_trets = 0;
			for ( int i = 0 ; i < this.trets.size() ; i++ ) {
				total_trets++;
				trets += "\t\t user:" + this.trets.get(i).getFirst();
				trets += " - fitxer:" + this.trets.get(i).getSecond() + "\n";
			}

			out += "\n\tFitxers descartats (" + total_trets +")";//:\n" + trets;

			out += "\n";
		}
		
		return out;
		
	}
	
    /**
     * funcio que per cada fitxer busca entre els servidors als que esta i retorna el 
     * servidor que te menys temps acumulat
     * @param llistaServFitxer
     * @param tamLlistServ
     * @return 
     */
    private int buscarServ(Set<Integer> llistaServFitxer) {
        int serv = 0;
        int tempsMin = 0;
        for(Integer i : llistaServFitxer){
            if(serv >= TxServer[i]){
                tempsMin = TxServer[i];
                serv = i;
            }
        }
        return serv;
    }
	
	
}
